package com.astrob.util;

import android.app.Activity;
import android.content.Context;

import com.astrob.mapsforge.MapsForgeTileProvider;
import com.astrob.mapsforge.MapsForgeTileSource;
import com.astrob.naviframe.Start;

import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.android.rendertheme.AssetsRenderTheme;
import org.mapsforge.map.rendertheme.XmlRenderTheme;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.modules.ArchiveFileFactory;
import org.osmdroid.tileprovider.modules.GEMFFileArchive;
import org.osmdroid.tileprovider.modules.IArchiveFile;
import org.osmdroid.tileprovider.modules.OfflineTileProvider;
import org.osmdroid.tileprovider.tilesource.FileBasedTileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.views.MapView;

import java.io.File;
import java.io.FileFilter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 支持加载离线地图（格式包括zip，sqlite，mbtiles，gemf，map五种格式）
 * 离线地图放在/com_map/map目录下
 */
public class SomeDataMapManger {


    public static void initmapViewData2(MapView mapView, Activity context) {

        Set<File> mapfiles = findMapFiles();
        File[] maps = new File[mapfiles.size()];
        maps = mapfiles.toArray(maps);
        if (maps == null || maps.length == 0) {
            mapView.setTileSource(TileSourceFactory.MAPNIK);
        } else {
            XmlRenderTheme theme = null;
            try {
                MapsForgeTileSource.createInstance(context.getApplication());

                theme = new AssetsRenderTheme(context.getApplicationContext(), "renderthemes/", "rendertheme-v4.xml");
                fromFiles = MapsForgeTileSource.createFromFiles(maps, theme, "rendertheme-v4");
                forge = new MapsForgeTileProvider(
                        new SimpleRegisterReceiver(context),
                        fromFiles, null);
                mapView.setTileProvider(forge);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    public static void initmapViewData(MapView mapView, Activity context) {

//        String path = FilePathManage.GetInstance().getMapDirectory() + "/";
        String path = Start.RUNDIR + "/mapsforge/";
        String fileName = "china.map";
//        String fileName = "js.gemf";
        String strFilepath = path + fileName;
        File exitFile = new File(strFilepath);
        if (!exitFile.exists() && !fileName.contains(".")) {
            mapView.setTileSource(TileSourceFactory.MAPNIK);
        } else {
            //加载map地图格式
            if (fileName.contains(".map")) {
                File[] mapfile = new File[1];
                mapfile[0] = exitFile;
                XmlRenderTheme theme = null;
                try {
                    theme = new AssetsRenderTheme(context, "renderthemes/", "rendertheme-v4.xml");
                    MapsForgeTileSource.createInstance(context.getApplication());
                    MapsForgeTileProvider forge = new MapsForgeTileProvider(new SimpleRegisterReceiver(context),
                            MapsForgeTileSource.createFromFiles(mapfile, theme, "rendertheme-v4"), null);
                    mapView.setTileProvider(forge);
                } catch (Exception ex) {
                    ex.printStackTrace();
                    return;
                }
                return;
            }
            fileName = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (fileName.length() == 0)
                return;
            /**
             *
             *  extensionMap.put("zip", ZipFileArchive.class);
             if(VERSION.SDK_INT >= 10) {
             extensionMap.put("sqlite", DatabaseFileArchive.class);
             extensionMap.put("mbtiles", MBTilesFileArchive.class);
             extensionMap.put("gemf", GEMFFileArchive.class);
             }
             这里加载上面四种地图格式
             */
//            if(Build.VERSION.SDK_INT >= 10) {
//                extensionMap.put("gemf", GEMFFileArchive.class);
//            }

            if (ArchiveFileFactory.isFileExtensionRegistered(fileName)) {
                try {
                    OfflineTileProvider tileProvider = new OfflineTileProvider((IRegisterReceiver) new SimpleRegisterReceiver(context),
                            new File[]{exitFile});
                    mapView.setTileProvider(tileProvider);

                    String source = "";
                    IArchiveFile[] archives = tileProvider.getArchives();
                    if (archives.length > 0) {
                        Set<String> tileSources = archives[0].getTileSources();
                        if (!tileSources.isEmpty()) {
                            source = tileSources.iterator().next();
                            mapView.setTileSource(FileBasedTileSource.getSource(source));
                        } else {
                            mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
                        }
                        //<---test
//                        FileBasedTileSource tileSource = (FileBasedTileSource)FileBasedTileSource.getSource(source);
//                        MapTile tile = new MapTile(15, 27192, 13298);
//                        GEMFFileArchive w = (GEMFFileArchive)archives[0];
//                        InputStream a  = w.getInputStream(tileSource, tile);
//                        tileSource.getDrawable(a);
                        //--->
                    } else
                        mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    //加载其他离线瓦片图 strFilepath-- ; 分隔
    public static void initmapViewData3(MapView mapView, Context context, String strFilepaths) {

        if (strFilepaths.length() < 1) {
            return;
        }

        String[] strFiles = strFilepaths.split(";");
        if (strFiles == null || strFiles.length < 1) {
            return;
        }
        int size = strFiles.length;
        File[] exitFiles = new File[size];
        for (int i = 0; i < size; i++) {
            exitFiles[i] = new File(strFiles[i]);
        }

        try {
            OfflineTileProvider tileProvider = new OfflineTileProvider((IRegisterReceiver) new SimpleRegisterReceiver(context),
                    exitFiles);
            mapView.setTileProvider(tileProvider);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    static MapsForgeTileSource fromFiles = null;
    static MapsForgeTileProvider forge = null;

    public static void detach() {
        if (fromFiles != null)
            fromFiles.dispose();
        if (forge != null)
            forge.detach();
        fromFiles = null;
        forge = null;
        AndroidGraphicFactory.clearResourceMemoryCache();
    }

    /**
     * simple function to scan for paths that match /something/osmdroid/*.map to find mapforge database files
     *
     * @return
     */
    protected static Set<File> findMapFiles() {
        Set<File> maps = new HashSet<>();
        List<StorageUtils.StorageInfo> storageList = StorageUtils.getStorageList();
        for (int i = 0; i < storageList.size(); i++) {
            File f = new File(storageList.get(i).path + File.separator + "com_map" + File.separator);
            if (f.exists()) {
                maps.addAll(scan(f));
            }
        }

        if (maps.size() < 1) {
            String path = "/storage/5105-1902/";// /mnt/media_rw/5105-1902
            File f = new File(path + "com_map/map/");
            if (f.exists()) {
                maps.addAll(scan(f));
            }
        }


        return maps;
    }

    static private Collection<? extends File> scan(File f) {
        List<File> ret = new ArrayList<>();
        File[] files = f.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().toLowerCase().endsWith(".map"))
                    return true;
                return false;
            }
        });
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                ret.add(files[i]);
            }
        }
        return ret;
    }

}
